home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 176-200 / 190 / nethack / twee.zoo / unixtty.c < prev    next >
C/C++ Source or Header  |  1988-05-04  |  9KB  |  416 lines

  1. /*    SCCS Id: @(#)unixtty.c    2.3    88/03/31
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* tty.c - (Unix) version */
  4.  
  5. /* With thanks to the people who sent code for SYSV - hpscdi!jon,
  6.  * arnold@ucsf-cgl, wcs@bo95b, cbcephus!pds and others.
  7.  */
  8.  
  9. #include    <stdio.h>
  10. #include    "extern.h"
  11. #include    "hack.h"
  12. #include    "func_tab.h"
  13.  
  14. extern void savech();
  15.  
  16. #define    ON    1
  17. #define OFF    0
  18.  
  19. /*
  20.  * The distinctions here are not BSD - rest but rather USG - rest, as
  21.  * BSD still has the old sgttyb structure, but SYSV has termio. Thus:
  22.  */
  23. #ifdef BSD
  24. #define    V7
  25. #else
  26. #define USG
  27. #endif
  28.  
  29. /*
  30.  * Some systems may have getchar() return EOF for various reasons, and
  31.  * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs.
  32.  */
  33. #ifndef BSD
  34. #define    NR_OF_EOFS    20
  35. #endif
  36.  
  37.  
  38. #ifdef USG
  39.  
  40. #include    <termio.h>
  41. #define termstruct    termio
  42. #define kill_sym    c_cc[VKILL]
  43. #define erase_sym    c_cc[VERASE]
  44. #define EXTABS        TAB3
  45. #define tabflgs        c_oflag
  46. #define echoflgs    c_lflag
  47. #define cbrkflgs    c_lflag
  48. #define CBRKMASK    ICANON
  49. #define CBRKON        ! /* reverse condition */
  50. #define OSPEED(x)    ((x).c_cflag & CBAUD)
  51. #define GTTY(x)        (ioctl(0, TCGETA, x))
  52. /* STTY now modified to run under Sys V R3.    - may have to be #ifdef'ed */
  53. #define STTY(x)        (ioctl(0, TCSETAW, x))    /* TCSETAF? TCSETAW? */
  54.  
  55. #else    /* V7 */
  56.  
  57. #include    <sgtty.h>
  58. #define termstruct    sgttyb
  59. #define    kill_sym    sg_kill
  60. #define    erase_sym    sg_erase
  61. #define EXTABS        XTABS
  62. #define tabflgs        sg_flags
  63. #define echoflgs    sg_flags
  64. #define cbrkflgs    sg_flags
  65. #define CBRKMASK    CBREAK
  66. #define CBRKON        /* empty */
  67. #define OSPEED(x)    (x).sg_ospeed
  68. #define GTTY(x)        (gtty(0, x))
  69. #define STTY(x)        (stty(0, x))
  70.  
  71. #endif
  72.  
  73. extern short ospeed;
  74. static char erase_char, kill_char;
  75. static boolean settty_needed = FALSE;
  76. struct termstruct inittyb, curttyb;
  77.  
  78. /*
  79.  * Get initial state of terminal, set ospeed (for termcap routines)
  80.  * and switch off tab expansion if necessary.
  81.  * Called by startup() in termcap.c and after returning from ! or ^Z
  82.  */
  83. gettty(){
  84.     if(GTTY(&inittyb) < 0)
  85.         perror("Hack (gettty)");
  86.     curttyb = inittyb;
  87.     ospeed = OSPEED(inittyb);
  88.     erase_char = inittyb.erase_sym;
  89.     kill_char = inittyb.kill_sym;
  90.     getioctls();
  91.  
  92.     /* do not expand tabs - they might be needed inside a cm sequence */
  93.     if(curttyb.tabflgs & EXTABS) {
  94.         curttyb.tabflgs &= ~EXTABS;
  95.         setctty();
  96.     }
  97.     settty_needed = TRUE;
  98. }
  99.  
  100. /* reset terminal to original state */
  101. settty(s) char *s; {
  102.     clear_screen();
  103.     end_screen();
  104.     if(s) printf(s);
  105.     (void) fflush(stdout);
  106.     if(STTY(&inittyb) < 0)
  107.         perror("Hack (settty)");
  108.     flags.echo = (inittyb.echoflgs & ECHO) ? ON : OFF;
  109.     flags.cbreak = (CBRKON(inittyb.cbrkflgs & CBRKMASK)) ? ON : OFF;
  110.     setioctls();
  111. }
  112.  
  113. setctty(){
  114.     if(STTY(&curttyb) < 0)
  115.         perror("Hack (setctty)");
  116. }
  117.  
  118.  
  119. setftty(){
  120. register int ef = 0;            /* desired value of flags & ECHO */
  121. register int cf = CBRKON(CBRKMASK);    /* desired value of flags & CBREAK */
  122. register int change = 0;
  123.     flags.cbreak = ON;
  124.     flags.echo = OFF;
  125.     /* Should use (ECHO|CRMOD) here instead of ECHO */
  126.     if((curttyb.echoflgs & ECHO) != ef){
  127.         curttyb.echoflgs &= ~ECHO;
  128. /*        curttyb.echoflgs |= ef;                    */
  129.         change++;
  130.     }
  131.     if((curttyb.cbrkflgs & CBRKMASK) != cf){
  132.         curttyb.cbrkflgs &= ~CBRKMASK;
  133.         curttyb.cbrkflgs |= cf;
  134. #ifdef USG
  135.         /* be satisfied with one character; no timeout */
  136.         curttyb.c_cc[VMIN] = 1;        /* was VEOF */
  137.         curttyb.c_cc[VTIME] = 0;    /* was VEOL */
  138. #endif
  139.         change++;
  140.     }
  141.     if(change){
  142.         setctty();
  143.     }
  144.     start_screen();
  145. }
  146.  
  147.  
  148. /* fatal error */
  149. /*VARARGS1*/
  150. error(s,x,y) char *s; {
  151.     if(settty_needed)
  152.         settty((char *) 0);
  153.     printf(s,x,y);
  154.     putchar('\n');
  155.     exit(1);
  156. }
  157.  
  158. /*
  159.  * Read a line closed with '\n' into the array char bufp[BUFSZ].
  160.  * (The '\n' is not stored. The string is closed with a '\0'.)
  161.  * Reading can be interrupted by an escape ('\033') - now the
  162.  * resulting string is "\033".
  163.  */
  164. getlin(bufp)
  165. register char *bufp;
  166. {
  167.     register char *obufp = bufp;
  168.     register int c;
  169.  
  170.     flags.toplin = 2;        /* nonempty, no --More-- required */
  171.     for(;;) {
  172.         (void) fflush(stdout);
  173.         if((c = getchar()) == EOF) {
  174.             *bufp = 0;
  175.             return;
  176.         }
  177.         if(c == '\033') {
  178.             *obufp = c;
  179.             obufp[1] = 0;
  180.             return;
  181.         }
  182.         if(c == erase_char || c == '\b') {
  183.             if(bufp != obufp) {
  184.                 bufp--;
  185.                 putstr("\b \b"); /* putsym converts \b */
  186.             } else    bell();
  187.         } else if(c == '\n') {
  188.             *bufp = 0;
  189.             return;
  190.         } else if(' ' <= c && c < '\177') {
  191.                 /* avoid isprint() - some people don't have it
  192.                    ' ' is not always a printing char */
  193.             *bufp = c;
  194.             bufp[1] = 0;
  195.             putstr(bufp);
  196.             if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
  197.                 bufp++;
  198.         } else if(c == kill_char || c == '\177') { /* Robert Viduya */
  199.                 /* this test last - @ might be the kill_char */
  200.             while(bufp != obufp) {
  201.                 bufp--;
  202.                 putstr("\b \b");
  203.             }
  204.         } else
  205.             bell();
  206.     }
  207. }
  208.  
  209. getret() {
  210.     cgetret("");
  211. }
  212.  
  213. cgetret(s)
  214. register char *s;
  215. {
  216.     putsym('\n');
  217.     if(flags.standout)
  218.         standoutbeg();
  219.     putstr("Hit ");
  220.     putstr(flags.cbreak ? "space" : "return");
  221.     putstr(" to continue: ");
  222.     if(flags.standout)
  223.         standoutend();
  224.     xwaitforspace(s);
  225. }
  226.  
  227. char morc;    /* tell the outside world what char he used */
  228.  
  229. xwaitforspace(s)
  230. register char *s;    /* chars allowed besides space or return */
  231. {
  232. register int c;
  233.  
  234.     morc = 0;
  235.  
  236.     while((c = readchar()) != '\n') {
  237.         if(flags.cbreak) {
  238.         if(c == ' ') break;
  239.         if(s && index(s,c)) {
  240.             morc = c;
  241.             break;
  242.         }
  243.         bell();
  244.         }
  245.     }
  246. }
  247.  
  248. static int last_multi;
  249.  
  250. char *
  251. parse()
  252. {
  253.     static char inline[COLNO];
  254.     register foo;
  255.  
  256.     multi = 0;
  257.     flags.move = 1;
  258.     if(!Invisible) curs_on_u(); else home();
  259.     while((foo = readchar()) >= '0' && foo <= '9') {
  260.         multi = 10*multi+foo-'0';
  261. #ifdef DGKMOD
  262.         if (multi < 0 || multi > LARGEST_INT)
  263.             multi = LARGEST_INT;
  264.         if (multi > 9) {
  265.             remember_topl();
  266.             home();
  267.             cl_end();
  268.             printf("Count: %d", multi);
  269.         }
  270. #endif
  271.         last_multi = multi;
  272.     }
  273. # ifdef REDO
  274.     if (foo == DOAGAIN || in_doagain)
  275.         multi = last_multi;
  276.     else {
  277.         savech(0);    /* reset input queue */
  278.         savech(foo);
  279.     }
  280. # endif
  281.     if(multi) {
  282.         multi--;
  283.         save_cm = inline;
  284.     }
  285.     inline[0] = foo;
  286.     inline[1] = 0;
  287.     if(foo == 'g' || foo == 'G'){
  288.         inline[1] = getchar();
  289. #ifdef QUEST
  290.         if(inline[1] == foo) inline[2] = getchar(); else
  291. #endif
  292.         inline[2] = 0;
  293.     }
  294.     if(foo == 'm' || foo == 'M'){
  295.         inline[1] = getchar();
  296.         inline[2] = 0;
  297.     }
  298.     clrlin();
  299.     return(inline);
  300. }
  301.  
  302. char
  303. readchar() {
  304.     register int sym;
  305.  
  306.     (void) fflush(stdout);
  307.     if((sym = getchar()) == EOF)
  308. #ifdef NR_OF_EOFS
  309.     { /*
  310.        * Some SYSV systems seem to return EOFs for various reasons
  311.        * (?like when one hits break or for interrupted systemcalls?),
  312.        * and we must see several before we quit.
  313.        */
  314.         register int cnt = NR_OF_EOFS;
  315.         while (cnt--) {
  316.             clearerr(stdin);    /* omit if clearerr is undefined */
  317.             if((sym = getchar()) != EOF) goto noteof;
  318.         }
  319.         end_of_input();
  320.          noteof:    ;
  321.     }
  322. #else
  323.         end_of_input();
  324. #endif /* NR_OF_EOFS /**/
  325.     if(flags.toplin == 1)
  326.         flags.toplin = 2;
  327.     return((char) sym);
  328. }
  329.  
  330. end_of_input()
  331. {
  332.     settty("End of input?\n");
  333.     clearlocks();
  334.     exit(0);
  335. }
  336.  
  337. #ifdef COM_COMPL
  338. /* Read in an extended command - doing command line completion for
  339.  * when enough character have been entered to make a unique command.
  340.  * This is just a modified getlin().   -jsb
  341.  */
  342. get_ext_cmd(bufp)
  343. register char *bufp;
  344. {
  345.     register char *obufp = bufp;
  346.     register int c;
  347.     int com_index, index;
  348.  
  349.     flags.toplin = 2;        /* nonempty, no --More-- required */
  350.  
  351.     for(;;) {
  352.         (void) fflush(stdout);
  353.         if((c = readchar()) == EOF) {
  354.             *bufp = 0;
  355.             return;
  356.         }
  357.         if(c == '\033') {
  358.             *obufp = c;
  359.             obufp[1] = 0;
  360.             return;
  361.         }
  362.         if(c == erase_char || c == '\b') {
  363.             if(bufp != obufp) {
  364.                 bufp--;
  365.                 putstr("\b \b"); /* putsym converts \b */
  366.             } else    bell();
  367.         } else if(c == '\n') {
  368.             *bufp = 0;
  369.             return;
  370.         } else if(' ' <= c && c < '\177') {
  371.                 /* avoid isprint() - some people don't have it
  372.                    ' ' is not always a printing char */
  373.             *bufp = c;
  374.             bufp[1] = 0;
  375.             index = 0;
  376.             com_index = -1;
  377.  
  378.             while(extcmdlist[index].ef_txt != (char *) 0){
  379.                 if(!strncmp(obufp, extcmdlist[index].ef_txt,
  380.                 strlen(obufp)))
  381.                     if(com_index == -1) /* No matches yet*/
  382.                         com_index = index;
  383.                     else /* More than 1 match */
  384.                         com_index = -2;
  385.                 index++;
  386.             }
  387.             if(com_index >= 0){
  388.                 strcpy(obufp,
  389.                 extcmdlist[com_index].ef_txt);
  390.                 /* finish print our string */
  391.                 putstr(bufp);
  392.                 bufp = obufp; /* reset it */
  393.                 if(strlen(obufp) < BUFSIZ-1 &&
  394.                  strlen(obufp) < COLNO)
  395.                     /* set bufp at the end of our
  396.                      * string
  397.                      */
  398.                     bufp += strlen(obufp);
  399.             } else {
  400.                 putstr(bufp);
  401.                 if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
  402.                     bufp++;
  403.             }
  404.         } else if(c == kill_char || c == '\177') { /* Robert Viduya */
  405.                 /* this test last - @ might be the kill_char */
  406.             while(bufp != obufp) {
  407.                 bufp--;
  408.                 putstr("\b \b");
  409.             }
  410.         } else
  411.             bell();
  412.     }
  413.  
  414. }
  415. #endif COM_COMPL
  416.